package com.citc;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * @author xiejp on 2022/5/19
 * CompletableFuture常用方法
 * 1.获取结果和触发计算
 * 2.对计算结果进行处理
 * 3.对计算结果进行消费
 * 4.对计算结果进行选用
 * 5.对计算结果进行合并
 */
public class CompletableFutureApiDemo {

    public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
                3, 20, 1L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(30), Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());
        //m1(threadPoolExecutor);
        //m2();
        //m3();
        //m4();
        //m5();
        threadPoolExecutor.shutdown();
    }

    private static void m5() {
        //5.对计算结果进行合并
        System.out.println(CompletableFuture.supplyAsync(() -> {
            return 10;
        }).thenCombine(CompletableFuture.supplyAsync(() -> {
            return 20;
        }), (x, y) -> {
            return x + y;
        }).join());
    }

    /**
     * 4.对计算结果进行选用
     */
    private static void m4() {
        System.out.println(CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(1L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1;
        }).applyToEither(CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 2;
        }), r -> r).join());
    }

    /**
     * 3.对计算结果进行消费
     */
    private static void m3() {
        System.out.println(CompletableFuture.supplyAsync(() -> {
            return 1;
        }).thenApply(f -> {
            return f + 1;
        }).thenApply(f -> {
            return f + 3;
        }).thenAccept(r -> {
            System.out.println(r);
        }).join());
    }

    /**
     * 2.对计算结果进行处理
     */
    private static void m2() {
        System.out.println(CompletableFuture
                .supplyAsync(() -> 1)
                .handle((f, e) -> {
                    System.out.println("-------1");
                    int i = 10 / 0;
                    return f + 4;
                })
                .handle((f, e) -> f + 2)
                .handle((f, e) -> f + 3)
                .whenComplete((v, e) -> {
                    if (e == null) {
                        System.out.println("---result=" + v);
                    }
                }).exceptionally(e -> {
                    e.printStackTrace();
                    return null;
                }).join());
        //exceptionally  ------>try/catch
        //whenComplete   ------>try/finally
        //handle         ------>try/finally
        //thenApply 由于存在依赖关系,当前步骤有异常就叫停.
        //handle 有异常也可以往下一步走,根据带的异常参数可以进一步处理
    }

    /**
     * 1.获取结果和触发计算
     *
     * @param threadPoolExecutor
     * @throws InterruptedException
     * @throws ExecutionException
     * @throws TimeoutException
     */
    private static void m1(ThreadPoolExecutor threadPoolExecutor) throws InterruptedException, ExecutionException, TimeoutException {
        CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
            try {
                TimeUnit.SECONDS.sleep(2L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return 1;
        }, threadPoolExecutor);
        //1.获取结果和触发计算
        System.out.println(completableFuture.get());
        System.out.println(completableFuture.get(2L, TimeUnit.SECONDS));
        System.out.println(completableFuture.getNow(1024));
        System.out.println(completableFuture.complete(-1024) + "\t" + completableFuture.get());
    }
}
